﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tao.OpenGl;
using Tao.FreeGlut;
using TWiStEr.Math;
using System.Windows.Media;

namespace TWiStEr.OpenGL.Utilities {
	public static class OpenGLExtensions {
		public static void PrintText(this string pszText, int nX, int nY) {
			int lines = 0;

			/*
			 * Prepare the OpenGL state
			 */
			Gl.glDisable(Gl.GL_LIGHTING);
			Gl.glDisable(Gl.GL_DEPTH_TEST);
			Gl.glMatrixMode(Gl.GL_PROJECTION);
			Gl.glPushMatrix();
			Gl.glLoadIdentity();

			/*
			 * Have an orthogonal projection matrix set
			 */
			Gl.glOrtho(0, Glut.glutGet(Glut.GLUT_WINDOW_WIDTH),
					 0, Glut.glutGet(Glut.GLUT_WINDOW_HEIGHT),
					 -1, +1
			);

			/*
			 * Now the matrix mode
			 */
			Gl.glMatrixMode(Gl.GL_MODELVIEW);
			Gl.glPushMatrix();
			Gl.glLoadIdentity();

			/*
			 * Now the main text
			 */
			Gl.glColor3ub(0, 0, 0);
			Gl.glRasterPos2i(nX, nY);

			for (int i = 0; i < pszText.Length; i++) {
				char p = pszText[i];
				if (p == '\n') {
					lines++;
					Gl.glRasterPos2i(nX, nY - (lines * 18));
				}

				Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_HELVETICA_18, (int)p);
			}

			/*
			 * Revert to the old matrix modes
			 */
			Gl.glMatrixMode(Gl.GL_PROJECTION);
			Gl.glPopMatrix();

			Gl.glMatrixMode(Gl.GL_MODELVIEW);
			Gl.glPopMatrix();

			/*
			 * Restore the old OpenGL states
			 */
			Gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
			Gl.glEnable(Gl.GL_DEPTH_TEST);
			Gl.glEnable(Gl.GL_LIGHTING);
		}
		#region gl* Commands
		public static void glTranslate(this Vector v) { Gl.glTranslated(v.X, v.Y, v.Z); }
		public static void glRotateAround(this Vector v, double angle) { Gl.glRotated(angle, v.X, v.Y, v.Z); }
		public static void glRotateAsNormal(this Vector v, Vector from) {
			double phi_delta, theta_delta;
			Vector.AnglesBetween(v, from, out phi_delta, out theta_delta);
			Gl.glRotated(phi_delta.ToDegree(), 0.0, 1.0, 0.0); // yrot
			Gl.glRotated(theta_delta.ToDegree(), 1.0, 0.0, 0.0); // xrot
		}
		public static void glutSolidSphere(this Vector v, double radius, int slices, int stacks) {
			Gl.glPushMatrix();
			v.glTranslate();
			Glut.glutSolidSphere(radius, slices, stacks);
			Gl.glPopMatrix();
		}
		public static void glScale(this Vector v) { Gl.glScaled(v.X, v.Y, v.Z); }
		public static void glNormal(this Vector v) { Gl.glNormal3d(v.X, v.Y, v.Z); }
		public static void glVertex(this Vector v) { Gl.glVertex3d(v.X, v.Y, v.Z); }
		public static void glVertex2(this Vector v) { Gl.glVertex2d(v.X, v.Y); }

		public static void glColor(this Color c) { Gl.glColor4ub(c.R, c.G, c.B, c.A); }
		public static void glColor3(this Color c) { Gl.glColor3ub(c.R, c.G, c.B); }
		#endregion


		public static void DrawVector(this Vector vector) {
			Gl.glBegin(Gl.GL_LINES);
			(-vector).glNormal();
			Vector.Zero.glVertex();
			vector.glNormal();
			vector.glVertex();
			Gl.glEnd();
		}
	}
}
